﻿using Microsoft.AspNetCore.Http;
using NewRetail.Application.Utility.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;

namespace NewRetail.Application.Utility
{
    public class UtilsHelper
    {
        #region 变量
        private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
        #endregion

        #region 获取时间
        /// <summary>
        /// 获取时间
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static string getFormatedDateString(string id)
        {
            DateTime timeNow = DateTime.Now;
            DateTime chinaTimeNow = DateTime.Now;
            try
            {
                TimeZoneInfo chinaZone = TimeZoneInfo.FindSystemTimeZoneById(id);
                chinaTimeNow = TimeZoneInfo.ConvertTime(timeNow, TimeZoneInfo.Local, chinaZone);
            }
            catch (TimeZoneNotFoundException)
            {
                //Console.WriteLine("The China Standard Time Zone cannot be found on the local system.");
            }
            return chinaTimeNow.ToString("yyyyMMddHHmmssfff");
        }
        #endregion

        #region Json序列号设置
        public static JsonSerializerSettings JsonSerSettings()
        {
            JsonSerializerSettings settings = new JsonSerializerSettings()
            {
                Formatting = Formatting.Indented,
                ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
            return settings;
        }
        #endregion

        #region SerializeObject
        /// <summary>
        /// 序列化返回字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static string SerializeObject<T>(T model)
        {
            return JsonConvert.SerializeObject(model, Formatting.None, _settings);
        }
        #endregion

        #region DeserializeObject
        /// <summary>
        /// 反序列化返回对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static T DeserializeObject<T>(string json)
        {
            return JsonConvert.DeserializeObject<T>(json);
        }
        #endregion

        #region DeserializeObject
        /// <summary>
        /// 反序列化返回对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static T DeserializeObject<T>(string json, JsonSerializerSettings settings)
        {
            return JsonConvert.DeserializeObject<T>(json, settings);
        }
        #endregion

        #region 将Stream转成 byte[]
        /// <summary>
        /// 将Stream转成 byte[]
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始 
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }
        #endregion

        #region 将byte[] 转成 Stream
        /// <summary>
        /// 将byte[] 转成 Stream
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static Stream BytesToStream(byte[] bytes)
        {
            Stream stream = new MemoryStream(bytes);
            return stream;
        }
        #endregion

        #region 使用指定字符集将string转换成byte[]

        /// <summary>
        /// 将string转换成byte[]
        /// </summary>
        /// <param name="text">要转换的字符串</param>
        public static byte[] StringToBytes(string text)
        {
            return Encoding.Default.GetBytes(text);
        }

        /// <summary>
        /// 使用指定字符集将string转换成byte[]
        /// </summary>
        /// <param name="text">要转换的字符串</param>
        /// <param name="encoding">字符编码</param>
        public static byte[] StringToBytes(string text, Encoding encoding)
        {
            return encoding.GetBytes(text);
        }

        #endregion

        #region 使用指定字符集将byte[]转换成string

        /// <summary>
        /// 将byte[]转换成string
        /// </summary>
        /// <param name="bytes">要转换的字节数组</param>
        public static string BytesToString(byte[] bytes)
        {
            return Encoding.Default.GetString(bytes);
        }

        /// <summary>
        /// 使用指定字符集将byte[]转换成string
        /// </summary>
        /// <param name="bytes">要转换的字节数组</param>
        /// <param name="encoding">字符编码</param>
        public static string BytesToString(byte[] bytes, Encoding encoding)
        {
            return encoding.GetString(bytes);
        }
        #endregion

        #region post请求byte[]
        /// <summary>
        /// post请求byte[] 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static string PostString(string url, byte[] data, string contentType = "application/x-www-form-urlencoded")
        {
            var result = Post(url, data, contentType);
            return Encoding.UTF8.GetString(result);
        }
        #endregion

        #region post请求byte[] 终
        public static byte[] Post(string url, byte[] postData, string contentType = "application/x-www-form-urlencoded")
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = contentType;
#if NET
            using (var requestStream = request.GetRequestStream())
            {
                requestStream.Write(postData, 0, postData.Length);
                using (var response = request.GetResponse())
                {
                    using (var responseStream = response.GetResponseStream())
                    {
                        return responseStream.ReadBytes(response.ContentLength);
                    }
                }
            }
#else
            return Task.Run(async () =>
            {
                using (var requestStream = await request.GetRequestStreamAsync())
                {
                    requestStream.Write(postData, 0, postData.Length);
                    using (var response = await request.GetResponseAsync())
                    {
                        using (var responseStream = response.GetResponseStream())
                        {
                            return responseStream.ReadBytes(response.ContentLength);
                        }
                    }
                }
            }).Result;
#endif
        }
        #endregion

        #region Rsa签名
        /// <summary>
        /// Rsa签名
        /// </summary>
        /// <param name="message"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static string RsaSign(string message, string privateKey)
        {
            var result = string.Empty;

            //byte[] keyData = Convert.FromBase64String(privateKey);
            //using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
            //using (RSACng rsa = new RSACng(cngKey))
            //{
            //    byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
            //    result = Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
            //}

            RSA rsa = RSA.Create();//由于需要跨平台，因此只能RSA.Create()
            byte[] keyData = Convert.FromBase64String(privateKey);
            int len = keyData.Length;
            rsa.ImportPkcs8PrivateKey(keyData, out len);

            byte[] data = Encoding.UTF8.GetBytes(message);
            result = Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));

            return result;
        }
        #endregion

        #region 生成随机字符串
        /// <summary>
        /// 生成随机字符串
        /// </summary>
        /// <returns></returns>
        public static string GetNonceStr()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
        }
        #endregion

        #region 生成时间戳，标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
        /// <summary>
        /// 生成时间戳，标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        #endregion

        #region 获取QueryParameters
        /// <summary>
        /// 获取QueryParameters
        /// </summary>
        /// <param name="queryString"></param>
        /// <returns></returns>
        public static IDictionary<string, string> GetQueryParameters(QueryString queryString)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            if (queryString.HasValue)
            {
                var parms = string.Join("&", queryString.Value.TrimStart('?').Split('&').Select(s =>
                {
                    var kv = s.Split('=');
                    var k = kv[0].Replace("_", "");
                    var v = kv[1];
                    return $"{k}={v}";
                }));

                var queryList = parms.Split("&".ToCharArray());
                foreach (string key in queryList)
                {
                    if (!string.IsNullOrEmpty(key))
                    {
                        parameters.Add(key.Split("=".ToCharArray())[0].ToString(), key.Split("=".ToCharArray())[1].ToString());
                    }
                }
            }
            return parameters;
        }
        #endregion

        #region DateTime --> long
        public static long ConvertDateTimeToLong(DateTime dt, string id = "China Standard Time")
        {
            TimeZoneInfo chinaZone = TimeZoneInfo.FindSystemTimeZoneById(id);
            DateTime dtStart = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Local, chinaZone);
            //DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            TimeSpan toNow = dt.Subtract(dtStart);
            long timeStamp = toNow.Ticks;
            timeStamp = long.Parse(timeStamp.ToString().Substring(0, timeStamp.ToString().Length - 4));
            return timeStamp;
        }
        #endregion

        #region long --> DateTime
        public static DateTime ConvertLongToDateTime(long d, string id = "China Standard Time")
        {
            TimeZoneInfo chinaZone = TimeZoneInfo.FindSystemTimeZoneById(id);
            DateTime dtStart = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Local, chinaZone);
            //DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(d + "0000");
            TimeSpan toNow = new TimeSpan(lTime);
            DateTime dtResult = dtStart.Add(toNow);
            return dtResult;
        }
        #endregion

        #region 获取枚举项描述信息 例如GetEnumDesc(ErrorCode.Success) 
        /// <summary>    
        /// 获取枚举项描述信息 例如GetEnumDesc(ErrorCode.Success)    
        /// </summary>    
        /// <param name="en">枚举项 如ErrorCode.Success</param>  
        /// <param name="iCode"></param> 
        /// <returns></returns>    
        public static string GetEnumDesc(Enum en, string iCode = "")
        {
            Type type = en.GetType();
            MemberInfo[] memInfo = type.GetMember(en.ToString());
            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs != null && attrs.Length > 0)
                {
                    return ((DescriptionAttribute)attrs[0]).Description;
                }
            }
            if (string.IsNullOrEmpty(iCode))
                return en.ToString();
            else
                return string.Concat(en.ToString(), "【" + iCode + "】");
        }
        #endregion

        #region 获取枚举项描述信息 例如GetEnumDescByVal(typeof(ReportFilingExceptionType),"other") 
        /// <summary>    
        /// 获取枚举项描述信息 例如GetEnumDescByVal(typeof(ReportFilingExceptionType),"other") 
        /// </summary>    
        /// <param name="enumType">枚举项</param> 
        /// <param name="enumValue">枚举项值 如other</param>  
        /// <returns></returns>    
        public static Dictionary<string, string> GetEnumDescByVal(Type enumType, string enumValue)
        {
            Dictionary<string, string> description = new Dictionary<string, string>();
            string strDescription = string.Empty;
            string strValue = string.Empty;
            if (enumType != null && enumType.IsEnum)
            {
                Type typeDescription = typeof(DescriptionAttribute);
                System.Reflection.FieldInfo[] fields = enumType.GetFields();

                foreach (System.Reflection.FieldInfo field in fields)
                {
                    if (field.FieldType.IsEnum)
                    {
                        //strValue = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString();
                        strValue = field.Name;
                        object[] arr = field.GetCustomAttributes(typeDescription, true);
                        if (arr.Length > 0)
                        {
                            DescriptionAttribute descriptionAttribute = (DescriptionAttribute)arr[0];
                            strDescription = descriptionAttribute.Description;
                        }
                        else
                        {
                            strDescription = field.Name;
                        }
                        if (strValue == enumValue)
                        {
                            description.Add(strValue, strDescription);
                            break;
                        }
                    }
                }
            }
            return description;
        }
        #endregion

        #region 将数据转换为双精度浮点型
        /// <summary>
        /// 将数据转换为双精度浮点型   转换失败返回默认值
        /// </summary>
        /// <typeparam name="T">数据的类型</typeparam>
        /// <param name="data">要转换的数据</param>
        /// <param name="defValue">默认值</param>
        /// <returns></returns>
        public static double ToDouble<T>(T data, double defValue)
        {
            //如果为空则返回默认值
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }

            try
            {
                return Convert.ToDouble(data);
            }
            catch
            {
                return defValue;
            }
        }

        /// <summary>
        /// 将数据转换为双精度浮点型,并设置小数位   转换失败返回默认值
        /// </summary>
        /// <typeparam name="T">数据的类型</typeparam>
        /// <param name="data">要转换的数据</param>
        /// <param name="decimals">小数的位数</param>
        /// <param name="defValue">默认值</param>
        /// <returns></returns>
        public static double ToDouble<T>(T data, int decimals, double defValue)
        {
            //如果为空则返回默认值
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }

            try
            {
                return Math.Round(Convert.ToDouble(data), decimals);
            }
            catch
            {
                return defValue;
            }
        }



        /// <summary>
        /// 将数据转换为双精度浮点型  转换失败返回默认值
        /// </summary>
        /// <param name="data">要转换的数据</param>
        /// <param name="defValue">默认值</param>
        /// <returns></returns>
        public static double ToDouble(object data, double defValue)
        {
            //如果为空则返回默认值
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }

            try
            {
                return Convert.ToDouble(data);
            }
            catch
            {
                return defValue;
            }

        }

        /// <summary>
        /// 将数据转换为双精度浮点型  转换失败返回默认值
        /// </summary>
        /// <param name="data">要转换的数据</param>
        /// <param name="defValue">默认值</param>
        /// <returns></returns>
        public static double ToDouble(string data, double defValue)
        {
            //如果为空则返回默认值
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }

            double temp = 0;

            if (double.TryParse(data, out temp))
            {
                return temp;
            }
            else
            {
                return defValue;
            }

        }


        /// <summary>
        /// 将数据转换为双精度浮点型,并设置小数位  转换失败返回默认值
        /// </summary>
        /// <param name="data">要转换的数据</param>
        /// <param name="decimals">小数的位数</param>
        /// <param name="defValue">默认值</param>
        /// <returns></returns>
        public static double ToDouble(object data, int decimals, double defValue)
        {
            //如果为空则返回默认值
            if (data == null || Convert.IsDBNull(data))
            {
                return defValue;
            }

            try
            {
                return Math.Round(Convert.ToDouble(data), decimals);
            }
            catch
            {
                return defValue;
            }
        }

        /// <summary>
        /// 将数据转换为双精度浮点型,并设置小数位  转换失败返回默认值
        /// </summary>
        /// <param name="data">要转换的数据</param>
        /// <param name="decimals">小数的位数</param>
        /// <param name="defValue">默认值</param>
        /// <returns></returns>
        public static double ToDouble(string data, int decimals, double defValue)
        {
            //如果为空则返回默认值
            if (string.IsNullOrEmpty(data))
            {
                return defValue;
            }

            double temp = 0;

            if (double.TryParse(data, out temp))
            {
                return Math.Round(temp, decimals);
            }
            else
            {
                return defValue;
            }
        }


        #endregion

        #region 天阙相关

        #region 获取天阙签名内容
        /// <summary>
        /// 获取天阙签名内容
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static string GetSignContent(IDictionary<string, object> parameters)
        {
            // 第一步：把字典按Key的字母顺序排序
            IDictionary<string, object> sortedParams = new SortedDictionary<string, object>(parameters);
            IEnumerator<KeyValuePair<string, object>> dem = sortedParams.GetEnumerator();

            // 第二步：把所有参数名和参数值串在一起
            StringBuilder query = new StringBuilder("");
            while (dem.MoveNext())
            {
                string key = dem.Current.Key;
                object value = dem.Current.Value;
                if (!string.IsNullOrEmpty(key) && value != null)
                {
                    if (key == "respData")
                    {
                        var respData = UtilConvert.ObjectToJSON(value);
                        var list = UtilConvert.RowFromJSON(respData);
                        value = DictionaryToStr(list);
                        query.Append(key).Append("=").Append(value).Append("&");
                    }
                    else
                    {
                        query.Append(key).Append("=").Append(value).Append("&");
                    }
                }
            }
            string content = query.ToString().Substring(0, query.Length - 1);

            return replaceStr(content);
        }
        #endregion

        #region 自己拼接一遍
        /// <summary>
        /// 自己拼接一遍
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static string DictionaryToStr(IDictionary<string, string> dic)
        {
            //使用排序字典
            //   dic = new SortedDictionary<string, string>(dic);
            string strTemp = "{";
            foreach (KeyValuePair<string, string> item in dic)
            {
                if (!string.IsNullOrEmpty(item.Key) && null != item.Value)
                {
                    strTemp += string.Format("\"{0}\":{1}", item.Key, UtilConvert.ObjectToJSON(item.Value));
                    strTemp += ",";
                }
            }
            strTemp = strTemp.ToString().Substring(0, strTemp.Length - 1);
            strTemp += "}";
            return strTemp;
        }
        #endregion

        #region 删除相关回车换行
        /// <summary>
        /// 删除相关回车换行
        /// </summary>
        /// <param name="b"></param>
        /// <returns></returns>
        public static string replaceStr(string b)
        {

            b = b.Replace("\r", ""); //删除百度\r
            b = b.Replace("\n", "");//删除\n
            b = b.Replace("\t", "");//删除\t
                                    //b = b.Replace(" ", "");//删除空格
            return b;
        }
        #endregion

        #endregion
    }
}
